package qc.common.core.utils;

import org.apache.commons.lang3.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * LocalDateTime工具类，将原先使用的Date类型替换为LocalDateTime类型
 *
 * @author QuCheng Tech
 * @since 2025/9/15
 */
public class LocalDateTimeUtil {

    /**
     * 日期格式，年月日，用横杠分开，例如：2006-12-25，2008-08-08
     */
    public static final String DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd";

    /**
     * 日期格式，年月日时分秒，年月日用横杠分开，时分秒用冒号分开
     * 例如：2005-05-10 23：20：00，2008-08-08 20:08:08
     */
    public static final String DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期转换格式（不包含时分秒），在将String转换为LocalDate或LocalDateTime时按列出的格式进行匹配转换
     */
    private static String[] DATE_PARSE_PATTERNS = {
            "yyyy-MM-dd", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM",
            "yyyyMMdd", "yyyyMM"};

    /**
     * 时间转换格式（包含时分秒），在将String转换为LocalDateTime时按列出的格式进行匹配转换
     * 2025-9-16实测pattern中的月日时分秒写2个字母在输入字符串中只有一个数字时无法匹配，pattern中的月日时分秒写1个字母时不管输入字符串中对应的数字时1个还是2个均能匹配；因此统一采用使用1个字母占位
     * 毫秒数必须精确匹配数字总个数，因此定义包含1、2、3个数字的不同毫秒数
     */
    private static String[] DATETIME_PARSE_PATTERNS = {
            "y-M-d H:m:s:S", "y-M-d H:m:s:SS", "y-M-d H:m:s:SSS", "y-M-d H:m:s.S", "y-M-d H:m:s.SS", "y-M-d H:m:s.SSS", "y-M-d H:m:s", "y-M-d H:m", "y-M-d H",//年月日使用-，中间使用空格，时分秒使用：
            "y-M-d'T'H:m:s:S", "y-M-d'T'H:m:s:SS", "y-M-d'T'H:m:s:SSS", "y-M-d'T'H:m:s.S", "y-M-d'T'H:m:s.SS", "y-M-d'T'H:m:s.SSS", "y-M-d'T'H:m:s", "y-M-d'T'H:m", "y-M-d'T'H",//年月日使用-，中间使用T，时分秒使用：
            "y/M/d H:m:s:S", "y/M/d H:m:s:SS", "y/M/d H:m:s:SSS", "y/M/d H:m:s.S", "y/M/d H:m:s.SS", "y/M/d H:m:s.SSS", "y/M/d H:m:s", "y/M/d H:m", "y/M/d H",//年月日使用/，中间使用空格，时分秒使用：
            "y/M/d'T'H:m:s:S", "y/M/d'T'H:m:s:SS", "y/M/d'T'H:m:s:SSS", "y/M/d'T'H:m:s.S", "y/M/d'T'H:m:s.SS", "y/M/d'T'H:m:s.SSS", "y/M/d'T'H:m:s", "y/M/d'T'H:m", "y/M/d'T'H",//年月日使用/，中间使用T，时分秒使用：
            "y.M.d H:m:s:S", "y.M.d H:m:s:SS", "y.M.d H:m:s:SSS", "y.M.d H:m:s.S", "y.M.d H:m:s.SS", "y.M.d H:m:s.SSS", "y.M.d H:m:s", "y.M.d H:m", "y.M.d H",//年月日使用.，中间使用空格，时分秒使用：
            "y.M.d'T'H:m:s:S", "y.M.d'T'H:m:s:SS", "y.M.d'T'H:m:s:SSS", "y.M.d'T'H:m:s.S", "y.M.d'T'H:m:s.SS", "y.M.d'T'H:m:s.SSS", "y.M.d'T'H:m:s", "y.M.d'T'H:m", "y.M.d'T'H",//年月日使用.，中间使用T，时分秒使用：
            "yyyyMMddHHmmssSSS", "yyyyMMddHHmmssSS", "yyyyMMddHHmmss", "yyyyMMddHHmm", "yyyyMMddHH"//内容全部连在一起，每个都固定数位（不足的前面补0）
    };

    /**
     * 获取当前的日期时间，包含毫秒数
     *
     * @return java.time.LocalDateTime
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDateTime getNow() {
        //去除毫秒数
        //return LocalDateTime.now().withNano(0x0);
        return LocalDateTime.now();
    }

    /**
     * 获取当前的日期时间
     *
     * @return java.time.LocalDateTime
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDateTime getToday() {
        return LocalDate.now().atStartOfDay();
    }

    /**
     * 获取当前的日期时间
     *
     * @return java.time.LocalDateTime
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDate getDate() {
        return LocalDate.now();
    }

    /**
     * 获取指定LocalDateTime的日期部分
     *
     * @param dateTime 日期时间
     * @return java.time.LocalDate
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDate getDate(LocalDateTime dateTime) {
        return dateTime.toLocalDate();
    }

    /**
     * 获取日期格式化字符串，默认为yyyy-MM-dd
     *
     * @param time 日期时间
     * @return java.lang.String
     * @author QuCheng Tech
     * @date 2022/11/21
     */
    public static String formatDate(LocalDateTime time) {
        return format(time, DATE_FORMAT_YYYY_MM_DD);
    }

    /**
     * 获取日期时间格式化字符串，默认为yyyy-MM-dd HH:mm:ss
     *
     * @param time 日期时间
     * @return java.lang.String
     * @author QuCheng Tech
     * @date 2022/11/21
     */
    public static String formatDateTime(LocalDateTime time) {
        return format(time, DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS);
    }

    /**
     * 将指定的date按指定的格式化字符串进行输出
     *
     * @param time    日期时间
     * @param pattern 格式化字符串
     * @return java.lang.String
     * @author QuCheng Tech
     * @date 2022/11/21
     */
    public static final String format(final LocalDateTime time, final String pattern) {
        if (time != null && StringUtils.isNotBlank(pattern)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

            return time.format(formatter);
        }

        return null;
    }

    /**
     * 将字符串解析为LocalDateTime，返回null表示解析不成功；使用默认的多种日期时间格式逐个进行解析
     *
     * @param str 日期时间字符串
     * @return java.time.LocalDateTime
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDateTime parse(String str) {
        //先使用日期时间的格式化进行解析，如果未解析出有效值再使用日期格式化格式再解析一次
        LocalDateTime time = parse(str, DATETIME_PARSE_PATTERNS);
        if (time != null)
            return time;

        LocalDate date = parseDate(str);
        if (date != null)
            return date.atStartOfDay();

        return null;
    }

    /**
     * 使用指定的格式化数组将字符串解析为LocalDateTime，返回null表示解析不成功
     *
     * @param str      日期时间字符串
     * @param patterns 格式化字符串
     * @return java.time.LocalDateTime
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDateTime parse(String str, String... patterns) {
        if (StringUtils.isNotBlank(str) && patterns != null && patterns.length > 0x0) {
            //逐个格式化解析，其中一个解析出来即返回
            for (String pattern : patterns) {
                LocalDateTime time = parse(str, pattern);
                if (time != null)
                    return time;
            }
        }

        return null;
    }

    /**
     * 使用指定的格式将字符串解析为LocalDateTime，返回null表示解析不成功
     *
     * @param str     日期时间字符串
     * @param pattern 格式化字符串
     * @return java.time.LocalDateTime
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDateTime parse(String str, String pattern) {
        //Objects.requireNonNull(pattern, "formatter");
        if (StringUtils.isNotBlank(str) && StringUtils.isNotBlank(pattern)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

            try {
                return LocalDateTime.parse(str, formatter);
            } catch (DateTimeParseException ex) {

            }
        }

        return null;
    }

    /**
     * 将字符串解析为LocalDate，返回null表示解析不成功；使用默认的多种日期时间格式逐个进行解析
     *
     * @param str 日期字符串
     * @return java.time.LocalDate
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDate parseDate(String str) {
        return parseDate(str, DATE_PARSE_PATTERNS);
    }

    /**
     * 使用指定的格式化数组将字符串解析为LocalDate，返回null表示解析不成功
     *
     * @param str      日期字符串
     * @param patterns 格式化字符串
     * @return java.time.LocalDate
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDate parseDate(String str, String... patterns) {
        if (StringUtils.isNotBlank(str) && patterns != null && patterns.length > 0x0) {
            //逐个格式化解析，其中一个解析出来即返回
            for (String pattern : patterns) {
                LocalDate date = parseDate(str, pattern);
                if (date != null)
                    return date;
            }
        }

        return null;
    }

    /**
     * 使用指定的格式将字符串解析为LocalDate，返回null表示解析不成功
     *
     * @param str     日期字符串
     * @param pattern 格式化字符串
     * @return java.time.LocalDate
     * @author QuCheng Tech
     * @since 2025/9/15
     */
    public static LocalDate parseDate(String str, String pattern) {
        //Objects.requireNonNull(pattern, "formatter");
        if (StringUtils.isNotBlank(str) && StringUtils.isNotBlank(pattern)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

            try {
                return LocalDate.parse(str, formatter);
            } catch (DateTimeParseException ex) {

            }
        }

        return null;
    }
}
